/* This file is apart of rtodo
 * 
 * Copyright (c) 2008, Ryan Capote
 * All rights reserved
 * Released under the BSD license
 */
 #include "rtodo.h"
 
 #include <iostream>
 #include <unistd.h>
 #include <fstream>
 #include <sstream>
 #include <cstring>
 
std::list<std::string> convertArguments(int argc, char *argList[])
{
    std::list<std::string> result;
    // We will start at 1 to ignore the
    // application name
    for(int x = 1; x < argc; x++)
    {
        // Converts the argument to a string
        // pushes it to the back of the list
        result.push_back(std::string(argList[x]));
    }
    
    return result;
}

std::string getCwd()
{
    // Get the current working directory
    char cwd[260];
    getcwd(cwd, 260);
    // Convert the ugly char array to a pretty string
    std::string result(cwd);
    return result;
}

void save(std::map<int, Task*> list, const std::string& path)
{
    std::ofstream file(path.c_str(), std::ios::out);
    if(file.is_open())
    {
        for(std::map<int, Task*>::iterator iter = list.begin(); iter != list.end(); iter++)
        {
            file << iter->second->serialize() << "\n";
        }
    }
    file.close();
}

void save(std::list<Task*> list, const std::string& path)
{
    std::ofstream file(path.c_str(), std::ios::out);
    if(file.is_open())
    {
        for(std::list<Task*>::iterator iter = list.begin(); iter != list.end(); iter++)
        {
            file << (*iter)->serialize() << "\n";
        }
    }
    file.close();
}

std::map<int, Task*> loadTodoMap(const std::string& path)
{
    std::map<int, Task*> result;
    std::string line;
    int id = 1;
    std::string filename = path;
    std::ifstream file(filename.c_str());
    
    if(file.is_open())
    {
        while(!file.eof())
        {
            std::getline(file, line);
            if(line.empty())
                break;
            result[id] = new Task(line, id);
            id++;            
        }
    }
    else
    {
        std::cout << "Cannot open " << filename << std::endl;
    }
    
    return result;
}

std::list<Task*> loadTodoList(const std::string& path)
{
    std::list<Task*> result;
    std::string line;
    int id = 1;
    std::string filename = path;
    std::ifstream file(filename.c_str());
    
    if(file.is_open())
    {
        while(!file.eof())
        {
            std::getline(file, line);
            if(line.empty())
                break;
            result.push_back(new Task(line, id));
            id++;            
        }
    }
    else
    {
        std::cout << "Cannot open " << filename << std::endl;
    }
    
    return result;
}

void view(int id, Task* task)
{
    std::cout << id
              << " "
              << task->serialize()
              << std::endl;
}

void viewTasks(std::map<int, Task*> list)
{
    std::map<int, Task*>::iterator iter;
    int count = 0;
    
    for(iter = list.begin(); iter != list.end(); iter++)
    {
        count++;
        view(iter->first, iter->second);
    }
    
    if(count == 0)
        std::cout << "There are no tasks." << std::endl;
}

void viewTasks(std::list<Task*> list)
{
    std::list<Task*>::iterator iter;
    int count = 0;
    
    for(iter = list.begin(); iter != list.end(); iter++)
    {
        count++;
        view((*iter)->getId(), (*iter));
        
    }
    
    if(count == 0)
        std::cout << "There are no tasks." << std::endl;
}

void viewProject(const std::string& project, std::map<int, Task*> list)
{
    std::map<int, Task*>::iterator iter;
    int count = 0;
    for(iter = list.begin(); iter != list.end(); iter++)
    {
        if(iter->second->getProject() == project)
        {
            count++;
            view(iter->first, iter->second);    
                      
        }
    }
    
    if(count == 0)
        std::cout << "No tasks for " << project << " were found." << std::endl;
} 

void viewProject(const std::string& project, std::list<Task*>& list)
{
    std::list<Task*>::iterator iter;
    int count = 0;
    for(iter = list.begin(); iter != list.end(); iter++)
    {
	//std::cout << "Proj: " << (*iter)->getProject() << " = " << project << std::endl;
        if((*iter)->getProject() == project)
        {
            count++;
            view((*iter)->getId(), (*iter));    
                      
        }
    }
    
    if(count == 0)
        std::cout << "No tasks for " << project << " were found." << std::endl;
} 

void viewContext(const std::string& context, std::map<int, Task*> list)
{
    std::map<int, Task*>::iterator iter;
    int count = 0;
    for(iter = list.begin(); iter != list.end(); iter++)
    {
        if(iter->second->getContext() == context)
        {
            count++;
            view(iter->first, iter->second);           
                      
        }
    }
    
    if(count == 0)
        std::cout << "No tasks for context " << context << " were found." << std::endl;
}

void viewContext(const std::string& context, std::list<Task*> list)
{
    std::list<Task*>::iterator iter;
    int count = 0;
    for(iter = list.begin(); iter != list.end(); iter++)
    {
        if((*iter)->getContext() == context)
        {
            count++;
            view((*iter)->getId(), (*iter));           
                      
        }
    }
    
    if(count == 0)
        std::cout << "No tasks for context " << context << " were found." << std::endl;
} 

void viewNext(std::map<int, Task*> list)
{
    std::map<int, Task*>::iterator iter;
    int count = 0;
    
    for(iter = list.begin(); iter != list.end(); iter++)
    {
        if(iter->second->isNext())
        {
            count++;
            view(iter->first, iter->second);
            
        }
    }
    
    if(count == 0)
        std::cout << "There are no next tasks." << std::endl;
}

void viewNext(std::list<Task*> list)
{
    std::list<Task*>::iterator iter;
    int count = 0;
    
    for(iter = list.begin(); iter != list.end(); iter++)
    {
        if((*iter)->isNext())
        {
            count++;
            view((*iter)->getId(), (*iter));
        }
    }
    
    if(count == 0)
        std::cout << "There are no next tasks." << std::endl;
}

std::list<Task*> prioritizeList(std::map<int, Task*> list, SortDir sort)
{
    std::map<int, Task*>::iterator iter;
    std::list<Task*> result;
    int start;
    int goal;
    
    if(sort == SORT_ASCENDING)
    {
        start = 0;
        goal = 5;
    }
    else if(sort == SORT_DESCENDING)
    {
        start = 5;
        goal = 0;
    }
    
    for(int priority = start; priority != goal; )
    {
        for(iter = list.begin(); iter != list.end();)
        {
            if(iter->second->getPriority() == priority)
            {
                result.push_back(iter->second);
                list.erase(iter++);
            }
            else
            {
                iter++;
            }
        }
        
        if(sort == SORT_ASCENDING)
        {
            priority++;
        }
        else if(sort == SORT_DESCENDING)
        {
            priority--;
        }
    }
    
    return result;   
}

std::list<Task*> prioritizeList(std::list<Task*> list, SortDir sort)
{
    std::list<Task*>::iterator iter;
    std::list<Task*> result;
    int start;
    int goal;
    int mod;
    
    if(sort == SORT_ASCENDING)
    {
        start = 0;
        goal = 6;
        mod = 1;
    }
    else if(sort == SORT_DESCENDING)
    {
        start = 6;
        goal = 0;
        mod = -1;
    }
    
    for(int priority = start; priority != goal; priority += mod )
    {
        for(iter = list.begin(); iter != list.end();)
        {
            if((*iter)->getPriority() == (mod + priority)*1)
            {
                result.push_back((*iter));
                list.erase(iter++);
            }
            else
            {
                iter++;
            }
        }
        
    }
    
    return result;   
}

void clearList(std::map<int, Task*>& list)
{
    std::cout << "This will permamently delete all finished tasks." << std::endl;
    std::cout << "Are you sure you want to continue(y/n)?" << std::endl;
    char answer;
    
    std::cin >> answer;
    
    if(answer == 'y')
    {
    
        std::map<int, Task*>::iterator iter;
        
        for(iter = list.begin(); iter != list.end();)
        {
            if(iter->second->isDone())
            {
                list.erase(iter++);
            }
            else
            {
                iter++;
            }
        }
    }

}

void clearList(std::list<Task*>& list)
{
    std::cout << "This will permamently delete all finished tasks." << std::endl;
    std::cout << "Are you sure you want to continue(y/n)?" << std::endl;
    char answer;
    
    std::cin >> answer;
    
    if(answer == 'y')
    {
        std::list<Task*>::iterator iter;
        
        for(iter = list.begin(); iter != list.end();)
        {
            if((*iter)->isDone())
            {
                list.erase(iter++);
            }
            else
            {
                iter++;
            }
        }
    }

}

void toggleDone(std::list<Task*>& list, int id)
{
    std::list<Task*>::iterator iter;
    
    for(iter = list.begin(); iter != list.end(); iter++)
    {
        if((*iter)->getId() == id)
        {
            (*iter)->toggleDone();
            return;
        }
    }
}

void toggleNext(std::list<Task*>& list, int id)
{
    std::list<Task*>::iterator iter;
    
    for(iter = list.begin(); iter != list.end(); iter++)
    {
        if((*iter)->getId() == id)
        {
            (*iter)->toggleNext();
            return;
        }
    }
}

void changePriority(std::list<Task*>& list, int id, int priority)
{
    std::list<Task*>::iterator iter;

    for(iter = list.begin(); iter != list.end(); iter++)
    {
        if((*iter)->getId() == id)
	{
	     (*iter)->setPriority(priority);
	     return;
	}
    }
}

void changeContext(std::list<Task*>& list, int id, const std::string& context)
{
    std::list<Task*>::iterator iter;

    for(iter = list.begin(); iter != list.end(); iter++)
    {
	 if((*iter)->getId() == id)
	 {
	      (*iter)->setContext(context);
	      return;
	 }
    }
}

void changeProject(std::list<Task*>& list, int id, const std::string& project)
{
    std::list<Task*>::iterator iter;

    for(iter = list.begin(); iter != list.end(); iter++)
    {
	 if((*iter)->getId() == id)
	 {
	      (*iter)->setProject(project);
	      return;
	 }
    }

}

void changeTask(std::list<Task*>& list, int id, const std::string& task)
{
    std::list<Task*>::iterator iter;

    for(iter = list.begin(); iter != list.end(); iter++)
    {
	 if((*iter)->getId() == id)
	 {
	      (*iter)->setTask(task);
	      return;
	 }
    }

}


void addTask(const std::string& filename, const std::string& desc, int priority = 1, 
	 const std::string& context = "none", const std::string& project = "none")
{
     std::cout << "Add: " << desc << " " << project << " " << context << " " << priority << std::endl;
     std::list<Task*> list = loadTodoList(filename);
     list.push_back(new Task(desc, project, context, 0, priority));
     save(list, filename);
} 

void deleteTask(std::list<Task*>& list, int id)
{
    std::cout << "This will permamently delete the task." << std::endl;
    std::cout << "Are you sure you want to continue(y/n)?" << std::endl;
    char answer;
    
    std::cin >> answer;
    
    if(answer == 'y')
    {

    	std::list<Task*>::iterator iter;

   	for(iter = list.begin(); iter != list.end(); iter++)
    	{
	     if((*iter)->getId() == id)
	     {
	          list.erase(iter);
	           return;
	     }
        }
    }

}
